home *** CD-ROM | disk | FTP | other *** search
/ The Best of MacTutor - S…e Code for Volumes 1 to 5 / The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin / Source Code / #18 (Mar 87) / Printer LSP sources / PrintingStuff < prev    next >
Text File  |  1987-02-13  |  9KB  |  223 lines

  1. UNIT Printing;
  2.  
  3. INTERFACE
  4.  
  5.     USES
  6.         MacPrint, MyGlobals, Windows;
  7.  
  8.     PROCEDURE DoPrinting;
  9.  
  10.  
  11. IMPLEMENTATION
  12.  
  13. {---------Print out a document window-----------}
  14.  
  15.     PROCEDURE DoPrinting;
  16.  
  17.         CONST
  18.             bottommargin = 20;{ margins (in pixels) for document, inset from rPage }
  19.             leftmargin = 30;
  20.             rightmargin = 10;
  21.             topmargin = 36;
  22.  
  23.         VAR
  24.             txth : Handle;
  25.             printTE : TEHandle;
  26.             MyPPort : TPPrPort;
  27.             dlogptr : DialogPtr;
  28.             txtptr : Ptr;
  29.             linesperpage, height, firstoffset, lastoffset, leftpos, toppos, fstpos, lineno, lastline, linecount, pageno, firstpage, lastpage, numpages, copyno, numpasses, dummyitem, errno : INTEGER;
  30.             pagerect : Rect;
  31.             currstr, laststr, heading : Str255;
  32.             strh0, strh1, hdgstrh : StringHandle;
  33.             status : TPrStatus;
  34.             info : FontInfo;
  35.             lastonpage : ARRAY[0..99] OF INTEGER;    { last line # on each page }
  36.  
  37.     BEGIN
  38. {  This section images each page, using QuickDraw via TextEdit}
  39. {   A few special cases:}
  40. {     1. For spooled output (IW only), must image and then print}
  41. {    2. For IW draft mode, must send multiple copies ourself}
  42. {   This has been completely rewritten from skeleton code, for a number}
  43. {   of key reasons:}
  44. {       1. A location is calculated for each line and then DrawText is}
  45. {       used to draw the line.  This also requires setting the font}
  46. {       directly in the printing GrafPort.  The skeleton used TextBox}
  47. {       for each page; TextBox uses an EraseRect which, according to}
  48. {       Technical Note #72, is very slow on the LaserWriter.}
  49. {    2. We use crOnly, so only actual returns are used for line}
  50. {       breaks.  Thus, we don't need a new TECalText for the}
  51. {       printing destRect, but instead use the TextEdit lineStarts}
  52. {       established for display purposes.}
  53. {    3. This routine figures out what the actual pages selected are,}
  54. {       and then prints only those pages.  (The values of prJob.iFstPage}
  55. {       and iLstPage need to be fudged to do this.)}
  56. {    4. Put a heading on each page, showing page number.}
  57. {    5. Put up an Alert if a printing error is encountered.  Not strictly}
  58. {       necessary, since the most commonly found "errors" are user-}
  59. {       specified aborts that should be ignored.}
  60. {}
  61.  
  62.         printFlag := FALSE;    { so we don't print again }
  63.         DialogueDeactivate;
  64.         IF PrJobDialog(printHdl) THEN
  65.             BEGIN
  66.                 SetCursor(watchHdl^^);
  67. { Put up progress dialog }
  68.                 strh0 := GetString(STR_prepare);
  69.                 ParamText(strh0^^, '', '', '');
  70.                 dlogptr := GetNewDialog(DLOG_printing, NIL, Pointer(-1));
  71.                 DrawDialog(dlogptr);
  72.                 printTE := hTE;
  73.  
  74. { Calculate number of pages, and line numbers for each page }
  75.                 WITH printTE^^, printHdl^^.PrInfo DO
  76.                     BEGIN
  77.                         txth := hText;
  78.                         height := lineHeight;
  79.                         linecount := nLines;
  80.                         linesperpage := (rPage.bottom - rPage.top - bottommargin - topmargin) DIV height;
  81.                         pagerect := rPage;    { top margin allows for heading }
  82.                         pagerect.left := pagerect.left + leftmargin;
  83.                         pagerect.right := pagerect.right - rightmargin;
  84.                         pagerect.bottom := pagerect.top + topmargin + (linesperpage * height);
  85.                         fstpos := pagerect.top + topmargin + fontAscent;
  86.               { base line of first line of text in document }
  87.                     END; {WITH}
  88.                 lastonpage[0] := 0;
  89.                 pageno := 1;
  90.                 lineno := 0;
  91.                 WHILE lineno < linecount DO    { until we run out of pages }
  92.                     BEGIN
  93.                         lineno := lineno + linesperpage;
  94.                         IF lineno < linecount THEN    { all but last page }
  95.                             lastonpage[pageno] := lineno - 1    { last line on this page }
  96.                         ELSE                { last page }
  97.                             lastonpage[pageno] := linecount - 1;{ lines numbered 0..n }
  98.                         pageno := pageno + 1;
  99.                     END; {WHILE}
  100.                 numpages := pageno - 1;
  101.  
  102. { We could skip page calculations, but then we would image all pages and}
  103. {  Print Manager would print only those selected.  Obviously this is}
  104. {  inefficient for large documents.  Instead, fool Print Manager into}
  105. {  thinking enough pages are selected and then do actual printing starting}
  106. {  at the selected page.  This MUST be done before PrOpenDoc.        }
  107.                 WITH printHdl^^.PrJob DO
  108.                     BEGIN
  109.                         firstpage := iFstPage;    { page numbers requested }
  110.                         IF firstpage < 1 THEN
  111.                             firstpage := 1;
  112.                         lastpage := iLstPage;
  113.                         IF lastpage > numpages THEN
  114.                             lastpage := numpages;    { limit to available pages }
  115.                         numpages := lastpage - firstpage + 1; { actual length }
  116.                         iFstPage := 1;        { fool print manager }
  117.                         iLstPage := numpages;    { reset by next PrJobDialog }
  118. { Manual handling of multiple copies for draft mode only}
  119. {  ImageWriter spooling handles this directly; the LaserWriter PrJobDialog}
  120. {  always sets iCopies := 1 and hides the actual number of copies from us}
  121. {  Also set up appropriate progress message                 }
  122.                         IF bJDocLoop = bSpoolLoop THEN
  123.                             BEGIN
  124.                                 numpasses := 1;        { only one pass through }
  125.                                 strh0 := GetString(STR_spooling);{ "Now spooling " }
  126.                             END
  127.                         ELSE
  128.                             BEGIN
  129.                                 numpasses := iCopies;        { draft mode, multiple passes }
  130.                                 strh0 := GetString(STR_printing);{ "Now printing " }
  131.                             END;
  132.                     END; {WITH}
  133.                 strh1 := GetString(STR_of);        { " of " }
  134.                 hdgstrh := GetString(STR_pagehead);    { "Page " }
  135.  
  136. { Now do actual printing (or imaging, for spool mode}
  137. {  Get a drawing port: TPrint should be frozen by now}
  138. {  Go through it once for every copy (if necessary) and once per page }
  139. {  Show dialog progress in terms of pages to be printed            }
  140.                 MyPPort := PrOpenDoc(printHdl, NIL, NIL);
  141.                 NumToString(numpages, laststr);    { actual # of pages to print }
  142.                 FOR copyno := 1 TO numpasses DO
  143.                     BEGIN
  144.                         MoveHHi(txth);
  145.                         HLock(txth);
  146.                         txtptr := txth^;
  147.  
  148.                         FOR pageno := firstpage TO lastpage DO
  149.                             BEGIN    { Image each page; this does printing for draft mode }
  150.                                 IF PrError = noErr THEN
  151.                                     BEGIN
  152.                                         NumToString(pageno - firstpage + 1, currstr); {relative page #}
  153.                                         ParamText(strh0^^, currstr, strh1^^, laststr);
  154.                                         DrawDialog(dlogptr);        { update the status }
  155.  
  156.                                         PrOpenPage(MyPPort, NIL);    { changes GrafPort for us }
  157. { First put a heading on the page.  Since MoveTo location for drawing text}
  158. {  is the base line, need ascent to position heading within pagerect }
  159.                                         TextFont(myHdgFont);
  160.                                         TextSize(myHdgSize);
  161.                                         GetFontInfo(info);        { need ascent height }
  162.                                         NumToString(pageno, heading);    { absolute page number }
  163.                                         heading := Concat(hdgstrh^^, heading); { "Page 1" }
  164.                                         WITH pagerect DO
  165.                                             BEGIN
  166.                                                 leftpos := left + ((right - left - StringWidth(heading)) DIV 2);        { center }
  167.                                                 MoveTo(leftpos, top + info.ascent); { base line }
  168.                                                 DrawString(heading);    { print page heading }
  169. { Now print actual document for this page }
  170.                                                 leftpos := left;        { left margin for text }
  171.                                                 toppos := fstpos;        { base line for 1st line }
  172.                                             END;
  173.                                         TextFont(printTE^^.txFont);    { set for display }
  174.                                         TextSize(printTE^^.txSize);
  175.                                         lineno := lastonpage[pageno - 1];{ line of TERec }
  176.                                         firstoffset := printTE^^.lineStarts[lineno];
  177.                                         lastline := lastonpage[pageno];
  178. { Draw each line in TERec, excluding CR at end of line }
  179.                                         WHILE lineno <= lastline DO
  180.                                             BEGIN
  181.                                                 MoveTo(leftpos, toppos);
  182.                                                 lineno := lineno + 1;
  183.                                                 IF lineno >= linecount THEN
  184.                                                     lastoffset := printTE^^.teLength  { very last line }
  185.                                                 ELSE
  186.                                                     lastoffset := printTE^^.lineStarts[lineno] - 1;
  187.                                                 DrawText(txtptr, firstoffset, lastoffset - firstoffset);
  188.                                                 toppos := toppos + height;
  189.                                                 firstoffset := lastoffset + 1;
  190.                                             END; {each line}
  191.                                         PrClosePage(MyPPort);        { done with this page }
  192.                                     END; {If no Prerror}
  193.                             END; {for each page}
  194.  
  195.                         HUnLock(txth);
  196.                     END; {each copy}
  197.                 PrCloseDoc(MyPPort);
  198. { If spooled, the file is now imaged and now need to print it }
  199.                 IF (printHdl^^.prJob.BJDocLoop = BSpoolLoop) AND (PrError = noErr) THEN
  200.                     BEGIN
  201.                         strh0 := GetString(STR_prspool);    { "Now printing spool file" }
  202.                         ParamText(strh0^^, '', '', '');
  203.                         DrawDialog(dlogptr);
  204.                         PrPicFile(printHdl, NIL, NIL, NIL, status);
  205.                     END;
  206. { Drop the advice dialog }
  207.                 DisposDialog(dlogptr);
  208.                 SetCursor(arrow);
  209.                 errno := PrError;
  210.                 IF (errno <> noErr) AND (errno <> iPrAbort) AND (errno <> iIOAbort) THEN  { indicate a printing error, unless… }
  211.     { user hit command-period }
  212.     { user cancel on "not responding" alert }
  213.                     BEGIN
  214.                         NumToString(errno, currstr);    { error number }
  215.                         ParamText(currstr, '', '', '');    { should be more user-friendly }
  216.                         dummyitem := StopAlert(ALRT_printerr, NIL);
  217.                     END;
  218.             END {IF PrJobDialog}
  219.         ELSE { Cancel in PrJobDlog }
  220.             PrSetError(iPrAbort);
  221.     END; {DoPrinting}
  222.  
  223. END.